<template>
  <div class="overflow-hidden relative bg-[#18181c]">
    <Header
      class="animate__animated animate__fadeInDown"
      id="driver_header"
      :layout="layout"
      :configsJson="configsJson"
      :savedId="savedId"
      :name="savedName"
      :ifImportFile="ifImportFile"
      :currentTemplate="currentTemplate"
      v-model:ifPreview="ifPreview"
      v-model:canShortKey="canShortKey"
      @importFile="importFileHandle"
      @showShortKeyList="showShortKeys = true"
    />

    <div class="flex">
      <!-- <LeftDragItem /> -->
      <LeftLayout
        id="driver_leftPart"
        class="animate__animated animate__slideInLeft"
      />
      <div class="bi-container flex-1 h-[calc(100vh-90px)!important]">
        <SketchRule
          :key="scale"
          :thick="rulerConfig.thick"
          :scale="scale"
          :lines="rulerConfig.lines"
          :startX="rulerConfig.startX"
          :startY="rulerConfig.startY"
          :palette="rulerConfig.palette"
          :ratio="rulerConfig.ratio"
          :shadow="rulerConfig.shadow"
          :width="centerWidth"
          :height="centerHeight"
        />
        <div
          class="screen"
          ref="$screenRef"
          @wheel="handleWheel"
          @scroll="handleScroll"
          @mousedown.stop="dragMousedown"
          @mouseup="dragMouseup"
          @mousemove="dragMousemove"
        >
          <div class="screen-container" ref="$screenContainerRef">
            <div
              class="canvas transition-all"
              ref="$canvasRef"
              :style="canvasStyle"
            >
              <div class="wrapper" id="driver_centerPart" :style="wrapperStyle">
                <div
                  class="containers animate__animated animate__fadeIn"
                  id="containercanvas"
                  ref="containercanvas"
                  :style="containerStyle"
                  @dragover.prevent
                  @drop="drops($event)"
                >
                  <div
                    class="mask select-none"
                    draggable="false"
                    v-show="showMask"
                    :style="computedStyle"
                  ></div>
                  <DraggableContainer
                    :style="wrapperStyle"
                    ref="dragContainer"
                    id="dragContainer"
                    @contextmenu.prevent="onContextMenu"
                  >
                    <Vue3DraggableResizable
                      :initW="it.width"
                      :initH="it.height"
                      v-for="it in layout"
                      :key="it.id"
                      :lockAspectRatio="it.lockAspectRatio"
                      v-model:x="it.x"
                      v-model:y="it.y"
                      v-model:w="it.width"
                      v-model:h="it.height"
                      v-model:active="it.active"
                      :draggable="true"
                      :resizable="it.resizable"
                      :data-id="it.id"
                      :parent="true"
                      @activated="onActivated(it)"
                      @deactivated="onDeactivated(it)"
                      @drag-start="start(it)"
                      @resize-start="start(it)"
                      @contextmenu.prevent="onContextMenuItem"
                      :style="{
                        'z-index': it.z,
                      }"
                      classNameHandle="!w-[15px] !h-[15px] !bg-[#3a89fe]"
                      class="maskTarget text-white box-border cursor-move will-change-transform border-none"
                      :class="[
                        it.animationClass,
                        pressSpace ? 'pointer-events-none' : '',
                      ]"
                    >
                      <div
                        @contextmenu.prevent="onContextMenuItem"
                        :data-id="it.id"
                        :class="{
                          'bg-[rgba(81,214,169,0.3)] border-[1px] border-[#3a89fe] border-[solid!important]':
                            it.id == currentId || combineIds.includes(it.id),
                        }"
                        :style="{
                          'z-index': it.z,
                        }"
                        class="absolute w-[100%] h-[100%] t-0 left-0"
                      ></div>
                      <component
                        :data-id="it.id"
                        :is="it.componentName"
                        ref="itRefs"
                        :id="it.id"
                        :staticData="it.staticData"
                        :width="it.width + 'px'"
                        :height="it.height + 'px'"
                        :iconName="it.iconName"
                        :imgName="it.imgName"
                        :componentType="it.componentType"
                        v-model:models="it.props"
                        v-model:responseData="it.responseData"
                        :themeColor="configsJson.themeColor"
                        @updateSize="updateSize"
                      ></component>
                    </Vue3DraggableResizable>
                  </DraggableContainer>
                </div>
              </div>
            </div>
          </div>
        </div>

        <BottomBar
          class="absolute bottom-0 left-0 w-[100%] animate__animated animate__slideInUp"
          v-model:scale="scale"
          v-model:lockScale="lockScale"
          @showShortKey="showShortKeys = true"
        />
      </div>

      <div
        id="driver_editPart"
        class="animate__animated animate__slideInRight w-[300px] bg-[#232324] h-[calc(100vh-90px)] border-l-[1px] border-l-[#18181c]"
      >
        <el-tabs
          @tab-change="tabsChange"
          v-model="activeName"
          class="bg-[#232324] w-[300px]"
        >
          <el-tab-pane label="全局属性" name="config" class="bg-[#232324]">
            <base_config v-model:models="configsJson" />
            <ThemeColor :configsJson="configsJson" />
          </el-tab-pane>
          <el-tab-pane
            label="组件属性"
            v-if="layout[currentIndex]"
            name="component"
          >
            <el-scrollbar :height="heights">
              <base_props
                v-if="activeName == 'component' && showRight"
                :layouts="layout"
                v-model:models="layout[currentIndex]"
              />
              <base_edit
                v-model:models="layout[currentIndex].props"
                v-if="
                  activeName == 'component' &&
                  showRight &&
                  layout[currentIndex].props.ifEcharts
                "
              />
              <component
                v-if="activeName == 'component' && showRight"
                :is="handleEditComp(layout[currentIndex].componentName)"
                v-model:models="layout[currentIndex].props"
                @edit="edithandle"
              ></component> </el-scrollbar
          ></el-tab-pane>
          <el-tab-pane
            v-if="layout[currentIndex]"
            label="动画"
            name="animation"
            class="bg-[#232324]"
          >
            <AnimationModule
              v-model:models="layout[currentIndex]"
              v-if="activeName == 'animation' && showRight"
            />
          </el-tab-pane>
          <el-tab-pane
            v-if="
              layout[currentIndex] &&
              Boolean(layout[currentIndex].canReq) &&
              showRight
            "
            label="数据源"
            name="data"
            class="bg-[#232324]"
          >
            <DataConfiModule v-model:layout="layout[currentIndex]" />
          </el-tab-pane>
          <el-tab-pane
            v-if="layout[currentIndex] && layout[currentIndex].props"
            label="事件交互"
            name="events"
            class="bg-[#232324]"
          >
            <EventComp
              v-if="layout[currentIndex] && activeName == 'events' && showRight"
              :layoutList="layout"
              v-model:layout="layout[currentIndex]"
            />
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>

    <NewContextMenu
      ref="newMenuRef"
      @operation="contextMenuClick"
      :layouts="layout"
    />

    <AnimationComp>
      <ShortKeys v-if="showShortKeys" v-model:showShortKeys="showShortKeys" />
    </AnimationComp>
  </div>
</template>

<script setup lang="ts">
import {
  clickMethod,
  mouseenterMethod,
  beforeMountMethod,
  mountedMethod,
  filterMethod,
} from "@renderer/utils/eventMethods";
import { useSnapShotStore } from "@renderer/store/modules/snapShot";
import EventComp from "@renderer/components/eventComp/index.vue";
import ShortKeys from "@renderer/components/shortkeys/index.vue";
import AnimationComp from "@renderer/components/animationComp/index.vue";
import BottomBar from "@renderer/components/bottomBar/index.vue";
import DataConfiModule from "@renderer/components/RequestModule/index.vue";
import AnimationModule from "@renderer/components/animationModule/index.vue";
import SketchRule from "vue3-sketch-ruler";
import "vue3-sketch-ruler/lib/style.css";
import Vue3DraggableResizable from "vue3-draggable-resizable";
import { DraggableContainer } from "vue3-draggable-resizable";
//default styles
import "vue3-draggable-resizable/dist/Vue3DraggableResizable.css";
import base_config from "@renderer/components/edit/base_config.vue";
import ThemeColor from "@renderer/components/themeColor/index.vue";
import base_props from "@renderer/components/edit/base_props.vue";
import base_edit from "@renderer/components/edit/base_edit.vue";
import * as allProps from "@renderer/components/config/index";
import Header from "@renderer/components/header/index.vue";
import LeftLayout from "@renderer/components/leftDragItem/leftLayout.vue";
import NewContextMenu from "@renderer/components/contextMenu/index.vue";

import useCombine from "@renderer/hooks/useCombine";
import { getTemplateDetail } from "@renderer/api/projectMenu";
import { debounce, findMaxValue, findMinValue } from "@renderer/utils/other";
import { useRoute } from "vue-router";
import { useMouseInElement } from "@vueuse/core";
import { useMask } from "@renderer/hooks/useDrawMask";
const { startX, startY, endX, endY, minX, maxX, minY, maxY } = useMask();
const route = useRoute();
const { ipcRenderer } = window;
const snapShotStore = useSnapShotStore();
import { useThemeConfigStore } from "@renderer/store/modules/themeConfig";

const themeConfigStore: any = useThemeConfigStore();
import { deepClone, stringify } from "@renderer/utils/other";
let newMenuRef = ref(null);

const onContextMenu = (e) => {
  e.preventDefault();
  e.stopPropagation();
  newMenuRef.value.onContextMenu(e);
};
const onContextMenuItem = (e) => {
  e.preventDefault();
  e.stopPropagation();
  let id = (e.currentTarget as any).dataset.id;
  if (id) {
    let item: any = layout.value.find((item: any) => item.id == id);
    console.log("item", item.active);
  }
  newMenuRef.value.onContextMenu(e);
};

import { useHotKey, bindKeys, unbindKeys } from "@renderer/hooks/useHotKey";
const { combineArr, combineIds, handleSize } = useCombine();
import {
  ref,
  onBeforeUnmount,
  onMounted,
  nextTick,
  computed,
  watch,
  provide,
  onUnmounted,
} from "vue";
import { throttle } from "@renderer/utils/other";
import Serves from "@renderer/utils/requestNew";
import { useDataSource } from "@renderer/hooks/useDataSource";
import { generateFilterFunc } from "@renderer/hooks/useEvents";
import { getDataSourceDetail } from "@renderer/api/dataSource";
import { handelResponseData } from "@renderer/utils/handleResponseData";
let configsJson = ref({
  backgroundColor: "#232324",
  backgroundImage: "",
  showBgImg: true,
  themeColor: [],
  width: 1920,
  height: 1080,
});
let showShortKeys = ref(false);
let showMask = ref(false);
let lockScale = ref(false);
let ifPreview = ref(false);
let canShortKey = ref(true);
let updateCanShortKey = (value) => {
  console.log("updateCanShortKey", value);
  canShortKey.value = value;
};

let updateSize = ({ w, h, id }) => {
  let index = layout.value.findIndex((it) => it.id == id);
  if (index >= 0) {
    layout.value[index].width = w;
    layout.value[index].height = h;
  }
};
provide("canShortKey", { canShortKey, updateCanShortKey });
const layout = ref([]);
const savedId = ref("");
const savedName = ref("");
const currentTemplate = ref({});
const renderDatas = async (id) => {
  if (id) {
    savedId.value = id as string;
    const res: any = await getTemplateDetail(id as string);

    if (res.code == 200) {
      currentTemplate.value = res.data;
      savedName.value = res.data.name;
      layout.value = JSON.parse(res.data.detail.layoutJson);
      configsJson.value = JSON.parse(res.data.detail.configJson);
      // console.log("layout", layout.value);
      // console.log("configsJson", configsJson.value);

      setNormalHandle();
    }
  } else {
    layout.value = [];
  }
};
let ifImportFile = ref(false);
const renderSize = () => {
  let size: any = route.query.size;
  if (!size) return;
  configsJson.value.width = JSON.parse(size).width;
  configsJson.value.height = JSON.parse(size).height;
};
const renderImportFile = () => {
  let file: any = route.query.file;
  if (!file) return;
  ElMessage.success("导入成功");
  ifImportFile.value = true;
  savedName.value = JSON.parse(file).name;
  layout.value = JSON.parse(file).layout;
  configsJson.value = JSON.parse(file).configsJson;
  setNormalHandle();
};

// 初始化接口、定时器轮询接口绑定
const setNormalHandle = () => {
  layout.value.forEach(async (item: any) => {
    let obj: any = {};
    // 判断是否使用数据源
    if (item.ifDataSource) {
      let real_Info: any = await getDataSourceDetail({
        id: item.dataSourceId,
      });
      if (real_Info.code == 200) {
        item.dataSourceInfo = real_Info.data;
        // console.log("item.dataSourceInfo ", item.dataSourceInfo);
      } else {
        ElMessage.error("数据源信息获取失败");
        return;
      }

      obj = await useDataSource(
        item.dataSourceInfo,
        JSON.parse(JSON.stringify(item.request))
      );
    } else {
      obj = JSON.parse(JSON.stringify(item.request));
    }
    if (item.request.ifInit && item.canReq) {
      try {
        let request = new Serves(obj.baseUrl).instance;
        if (obj.ifFormData) {
          let formdata = new FormData();
          for (let key in obj.data) {
            formdata.append(key, obj.data[key]);
          }
          obj.data = formdata;
        }
        const res = await request({
          ...obj,
        });
        const { data } = res;
        let filtedData = generateFilterFunc(
          item.eventMethods.filterMethod,
          data || {},
          res
        )();
        item.responseData = filtedData;
        item.props = handelResponseData(item.responseData, item);
      } catch (error) {
        ElMessage.error("接口数据获取失败：" + error);
      }
    }
  });
};
provide("refreshPage", {
  renderDatas,
});
let pressSpace = ref(false);
const spaceHandle = function (event) {
  event.preventDefault();
  // console.log("space", event.type);
  if (event.type == "keydown") {
    pressSpace.value = true;
    document.body.style.cursor = "pointer";
    currentId.value = "";
    showRight.value = false;
    activeName.value = "config";
  }
  if (event.type == "keyup") {
    pressSpace.value = false;
    document.body.style.cursor = "";
  }
};

watch(canShortKey, () => {
  unbindKeys("space", spaceHandle);
  if (canShortKey.value) {
    bindKeys("space", spaceHandle);
  } else {
    unbindKeys("space", spaceHandle);
  }
});

onUnmounted(() => {
  unbindKeys("space", spaceHandle);
});
onMounted(() => {
  snapShotStore.initSnapshot();
  ipcRenderer.send("setMainWindow", true);
  renderDatas(route.query.id);
  renderImportFile();
  renderSize();
  bindKeys("space", spaceHandle);

  ipcRenderer.on("ChildWinClose", (event, arg) => {
    ifPreview.value = false;
  });

  ipcRenderer.on("previewPageInitEdit", (event, arg) => {
    if (arg) {
      // let obj = {
      //   layout: JSON.stringify(layout.value),
      //   configsJson: JSON.stringify(configsJson.value),
      // };
      setTimeout(() => {
        // console.log("ffff!!!!!", obj);
        // ipcRenderer.send("infoToMain", obj);

        layout.value[0].width += 1;
        layout.value[0].width -= 1;
      }, 500);
    }
  });
});

const tabsChange = (name: string) => {
  if (name != "config" && !showRight.value) {
    ElMessage.info("请选择组件后操作");
  }
};

watch(
  () => themeConfigStore.currentThemeColor,
  () => {
    configsJson.value.themeColor = JSON.parse(
      JSON.stringify(themeConfigStore.currentThemeColor)
    );
  },
  { immediate: true, deep: true }
);

// 使用watch监听 layout和configsJson，并使用防抖优化
watch(
  [layout, configsJson],
  debounce(([layout, configsJson]) => {
    // console.log("layout change", layout);

    snapShotStore.addSnapshot(deepClone(layout));
    if (ifPreview.value) {
      let obj = {
        layout: stringify(layout),
        configsJson: stringify(configsJson),
      };
      // console.log("watchobj", layout);
      ipcRenderer.send("infoToMain", deepClone(obj));
    }
  }, 300),
  { deep: true }
);
onBeforeUnmount(() => {
  // 移除键盘事件的监听
  document.removeEventListener("keydown", function (event) {});
  document.removeEventListener("keyup", function (event) {});
  window.removeEventListener("mousemove", function () {});
  window.removeEventListener("mousedown", function () {});
  window.removeEventListener("mouseup", function () {});
});

const activeName = ref("config");
const heights = computed(() => {
  return window.innerHeight - 170 + "px";
});

const edithandle = () => {};

const importFileHandle = (value: any) => {
  ElMessageBox.confirm("导入文件将覆盖当前画布内容，是否继续？", "提示", {
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
  })
    .then(async () => {
      layout.value = [];
      // savedName.value = value.name;
      configsJson.value = value.configsJson;
      layout.value = value.layout;
      ElMessage.success("文件导入成功");
    })
    .catch(() => {});
};
function GenNonDuplicateID(randomLength) {
  return Number(
    Math.random().toString().substr(3, randomLength) + Date.now()
  ).toString(36);
}
const currentIndex = ref(0);
const currentId = ref("");
const showRight = ref(false);
const onActivated = (value) => {
  currentId.value = "";
  currentIndex.value = null;
  showRight.value = true;
  currentId.value = value.id;
  let index = layout.value.findIndex((it) => it.id == value.id);
  currentIndex.value = index;
  if (index >= 0) {
    layout.value.map((it) => (it.active = false));
    layout.value[index].active = true;
    // combineArr.value = [];
  }

  if (value.componentName == "combineGroup") {
    activeName.value = "config";
  }
  //  else {
  //   activeName.value = "component";
  // }
};

const handleEditComp = (componentName) => {
  if (componentName.includes("myBorder")) {
    return `edit_${"myBorder"}`;
  } else if (componentName.includes("myTextBorder")) {
    return `edit_${"myTextBorder"}`;
  } else if (componentName.includes("myDecoration")) {
    return `edit_${"myDecoration"}`;
  } else if (componentName.includes("myTextDecoration")) {
    return `edit_${"myTextDecoration"}`;
  } else {
    return `edit_${componentName}`;
  }
};
const containercanvas = ref(null);
const dragContainer = ref(null);
// 将最大外面的div设置滚动上下各50%以让画布居中
const $screenContainerRef = ref(null);
const $screenRef = ref(null);
const $canvasRef = ref(null);
const currentItem = computed(() => layout.value[currentIndex.value]);
const { x, y, isOutside } = useMouseInElement();
const copyedItem = ref<any>(null);
watch(copyedItem, () => {
  if (copyedItem.value) {
    newMenuRef.value.canPaste = true;
  } else {
    newMenuRef.value.canPaste = false;
  }
});
useHotKey("ctrl+c", () => {
  if (!canShortKey.value) return;
  // console.log("copyHandle");
  copyFunction();
});
useHotKey(
  "Delete",
  throttle(() => {
    if (!canShortKey.value) return;
    console.log("currentIndex", currentIndex.value);
    console.log(
      "delete",
      layout.value.filter((it) => it.active == true),
      combineIds.value
    );
    if (combineIds.value.length > 0) {
      combineIds.value.forEach((it) => {
        let index = layout.value.findIndex((item) => item.id == it);
        if (index >= 0) {
          layout.value.splice(index, 1);
        }
      });
    } else {
      if (currentIndex.value >= 0 && currentIndex.value != null) {
        layout.value.splice(currentIndex.value, 1);
      }
      // layout.value.splice(currentIndex.value, 1);
    }
    currentIndex.value = null;
    currentId.value = "";
    showRight.value = false;
    activeName.value = "config";
    combineArr.value = [];
  }, 200)
);
useHotKey(
  "ctrl+z",
  throttle(() => {
    if (!canShortKey.value) return;
    console.log("撤回啦");
    let res = snapShotStore.undo();
    // console.log("res", res);
    if (res.length <= 0) {
      return;
    }
    layout.value = res;
    // currentIndex.value = null;
    // currentId.value = "";
    // showRight.value = false;
    activeName.value = "config";
  }, 1000)
);
useHotKey("ctrl+v", () => {
  if (!canShortKey.value) return;
  nextTick(() => {
    pasteFunction();
  });
});
useHotKey("ctrl+x", () => {
  if (!canShortKey.value) return;
  cutFunction();
});
useHotKey("ctrl+l", () => {
  if (!canShortKey.value) return;
  lockScale.value = true;
});
useHotKey("ctrl+shift+l", () => {
  if (!canShortKey.value) return;
  lockScale.value = false;
});
useHotKey("alt+up", () => {
  if (!canShortKey.value) return;
  if (!currentItem.value) return;
  if (layout.value[currentIndex.value].y <= 0) return;
  layout.value[currentIndex.value].y -= 10;
});
useHotKey("alt+down", () => {
  if (!canShortKey.value) return;
  if (!currentItem.value) return;
  if (
    layout.value[currentIndex.value].y +
      layout.value[currentIndex.value].height >=
    configsJson.value.height
  )
    return;
  layout.value[currentIndex.value].y += 10;
});
useHotKey("alt+right", () => {
  if (!canShortKey.value) return;
  if (!currentItem.value) return;
  if (
    layout.value[currentIndex.value].x +
      layout.value[currentIndex.value].width >=
    configsJson.value.width
  )
    return;
  layout.value[currentIndex.value].x += 10;
});
useHotKey("alt+left", () => {
  if (!canShortKey.value) return;
  if (!currentItem.value) return;
  if (layout.value[currentIndex.value].x <= 0) return;
  layout.value[currentIndex.value].x -= 10;
});
useHotKey("ctrl+g", () => {
  if (!canShortKey.value) return;
  combindMethod();
});
useHotKey("ctrl+shift+g", () => {
  if (!canShortKey.value) return;
  cancleCombine();
});
const onDeactivated = (value) => {};
const start = (value) => {
  let index = layout.value.findIndex((it) => it.id == value.id);
  if (index >= 0) {
    layout.value.map((it) => (it.active = false));
    layout.value[index].active = true;
    currentIndex.value = index;
    currentId.value = value.id;
    // activeName.value = "component";
  }
};
const drops = (event) => {
  let componentName = event.dataTransfer.getData("name");

  if (!componentName) return;
  let canReq = event.dataTransfer.getData("canReq").includes("true") || false;
  let id = GenNonDuplicateID(6);
  let propAttr = null;
  if (componentName.includes("myBorder")) {
    propAttr = JSON.parse(JSON.stringify(allProps["myBorder"]));
  } else if (componentName.includes("myTextBorder")) {
    propAttr = JSON.parse(JSON.stringify(allProps["myTextBorder"]));
  } else if (componentName.includes("myDecoration")) {
    propAttr = JSON.parse(JSON.stringify(allProps["myDecoration"]));
  } else if (componentName.includes("myTextDecoration")) {
    propAttr = JSON.parse(JSON.stringify(allProps["myTextDecorations"]));
  } else if (componentName.includes("myIcons")) {
    propAttr = JSON.parse(JSON.stringify(allProps["myIcons"]));
  } else if (componentName.includes("myImgs")) {
    propAttr = JSON.parse(JSON.stringify(allProps["myImgs"]));
  } else {
    propAttr = deepClone(allProps[componentName]);
  }
  let labelName = event.dataTransfer.getData("labelName") + id;

  let iconName = event.dataTransfer.getData("iconname");
  let imgName = event.dataTransfer.getData("imgname");

  const containerReact = (
    containercanvas.value || document.querySelector("#containercanvas")
  ).getBoundingClientRect();
  let clickX = (event.clientX - containerReact.x) / scale.value;
  let clickY = (event.clientY - containerReact.y) / scale.value;
  let staticData = JSON.parse(
    JSON.stringify(allProps[componentName + "_staticData"] || {})
  );
  let maxZ = findMaxValue(layout.value, "z");
  console.log("propAttr", propAttr);
  layout.value.push({
    x: clickX - 10, //x
    y: clickY - 10, //y
    z: maxZ ? maxZ + 1 : 1, // z
    width: propAttr.com_width || 600,
    height: propAttr.com_height || 400,
    active: true,
    componentName, // 组件名
    componentLabelName: labelName, //中文名
    resizable: !componentName.includes("myIcons"),
    id: id,
    props: propAttr, // 相关属性
    iconName: iconName,
    imgName: imgName,
    ifDataSource: false, // 是否使用数据源
    dataSourceId: "", //数据源id
    dataSourceInfo: {}, //数据源信息
    request: {
      baseUrl: "",
      url: "",
      method: "get",
      data: {},
      params: {},
      headers: {},
      ifInit: false,
      ifPolling: false,
      pollingTime: null,
    }, // 数据请求相关信息
    responseData: staticData || [], // 用来接收组件数据
    staticData, // 组件默认使用的静态数据
    animationClass: "", //动画名称
    canReq, // 组件本身是否调用接口
    eventMethods: {
      clickMethod,
      mouseenterMethod,
      beforeMountMethod,
      mountedMethod,
      ifFilter: false,
      filterMethod,
    }, //事件交互和事件配置
  });
  currentIndex.value = layout.value.length - 1;
  showRight.value = true;
  currentId.value = id;
  activeName.value = "component";
  // console.log(layout.value[currentIndex.value]);
};

const rulerConfig = ref({
  scale: 1, //初始化标尺的缩放 通过设置值，改变刻度尺的大小
  thick: 20, //标尺的厚度
  lines: { h: [], v: [] }, //不能直接写{}不然删除有问题
  startX: 0,
  startY: 0,
  ratio: 1, //标尺缩放必须设置不然标尺的不正常
  shadow: {
    x: 0,
    y: 0,
    width: 0,
    height: 0,
  },
  palette: {
    bgColor: "#18181c", //整体个尺子背景颜色
    shortfgColor: "#87878d", //尺子短刻度颜色
    fontColor: "#87878d", //尺子刻度字体颜色
    lineColor: "#87878d", //标准线的颜色
  },
});
// 292两边宽度，20尺寸宽度 64上面头部高度60和22是预留上下左右空白
const fixWidth = 340;
const fixHeight = 350;

const scale = ref(1);

// 设置标尺大小
const initScale = () => {
  let w = window.innerWidth - fixWidth;
  let h = window.innerHeight - fixHeight;
  let ratew = w / configsJson.value.width;
  let rateh = h / configsJson.value.height;
  scale.value = Math.min(ratew, rateh);
};
initScale();

// 标尺所在中间尺寸宽604=292+292+20
const centerWidth = computed(() => {
  return window.innerWidth - 604;
});

// 标尺所在中间尺寸高85=64+20+1
const centerHeight = computed(() => {
  return window.innerHeight - 85;
});

// 设置画布大小
const canvasStyle = computed(() => {
  return {
    width: configsJson.value.width + "px",
    height: configsJson.value.height + "px",
    transform: `scale(${scale.value})`,
    transformOrigin: "0 0",
  };
});

// 设置真实画布大小
const wrapperStyle = computed(() => {
  return {
    width: configsJson.value.width + "px",
    height: configsJson.value.height + "px",
  };
});

// 设置内容区域
const containerStyle = computed(() => {
  return {
    transform: `scale(1, 1)`,
    width: configsJson.value.width + "px",
    height: configsJson.value.height + "px",
    backgroundColor: configsJson.value.backgroundColor,
    backgroundImage: configsJson.value.showBgImg
      ? `url(${configsJson.value.backgroundImage})`
      : "",
    backgroundPosition: "0% 0%",
    backgroundSize: "100% 100%",
    backgroundRepeat: "initial",
    backgroundAttachment: "initial",
    backgroundOrigin: "initial",
    backgroundClip: "initial",
  };
});

const initData = () => {
  let screenContaineDom = $screenContainerRef.value.getBoundingClientRect();
  $screenRef.value.scrollLeft =
    screenContaineDom.width / 2 - rulerConfig.value.thick - 20;
  $screenRef.value.scrollTop =
    screenContaineDom.height / 2 - rulerConfig.value.thick - 20;
  handleScroll();
};
nextTick(() => {
  initData();
});

// 滚动鼠标标尺也跟着滚动
const handleScroll = () => {
  const screenRect = $screenRef.value.getBoundingClientRect();
  const canvasRect = $canvasRef.value.getBoundingClientRect();
  let startX =
    (screenRect.left + rulerConfig.value.thick - canvasRect.left) / scale.value;
  let startY =
    (screenRect.top + rulerConfig.value.thick - canvasRect.top) / scale.value;
  rulerConfig.value.startX = startX >> 0;
  rulerConfig.value.startY = startY >> 0;
};

// 缩放（目前缩放之后，尺寸的值与画布稍有偏差需要精确）
const handleWheel = (e) => {
  if (lockScale.value) {
    return;
  }
  if (e.ctrlKey || e.metaKey) {
    e.preventDefault();
    scale.value = parseFloat((scale.value - e.deltaY / 1000) as any);
  }
};
// 点击空白移动鼠标进行尺子移动
//按下鼠标
const dragSlide = ref(false);
let computedStyle = computed(() => ({
  left: minX.value + "px",
  top: minY.value + "px",
  width: maxX.value - minX.value + "px",
  height: maxY.value - minY.value + "px",
  display: showMask.value ? "block" : "none",
}));
const dragMousedown = (e) => {
  if (
    e.target !== containercanvas.value &&
    e.target !== document.querySelector(".drv-container") &&
    e.target !== document.querySelector("#dragContainer")
  )
    return;

  currentId.value = "";
  showRight.value = false;
  activeName.value = "config";
  combineArr.value = [];
  if (e.type == "mousedown" && pressSpace.value && canShortKey.value) {
    layout.value.forEach((it) => (it.active = false));
    e.stopPropagation();
    e.preventDefault();
    dragSlide.value = true;
    (window as any).stardragEvent = e;
    (window as any).startSlideX = $screenRef.value.scrollLeft;
    (window as any).startSlideY = $screenRef.value.scrollTop;
  } else if (canShortKey.value) {
    const containerReact = (
      containercanvas.value || document.querySelector("#containercanvas")
    ).getBoundingClientRect();
    let clickX = (e.clientX - containerReact.x) / scale.value;
    let clickY = (e.clientY - containerReact.y) / scale.value;
    startX.value = clickX;
    startY.value = clickY;
    let dom =
      containercanvas.value || document.querySelector("#containercanvas");
    dom.addEventListener("mousemove", handleMouseMove); //监听鼠标移动事件
    dom.addEventListener("mouseup", handleMouseUp); //监听鼠标抬起事件
  }
};
const handleMouseUp = () => {
  showMask.value = false;
  judgeMaskMove();
  let dom = containercanvas.value || document.querySelector("#containercanvas");
  dom.removeEventListener("mousemove", handleMouseMove);
  dom.removeEventListener("mouseup", handleMouseUp);
};

const handleMouseMove = (e) => {
  // console.log("!!!移动着呢");
  showMask.value = true;
  const containerReact = (
    containercanvas.value || document.querySelector("#containercanvas")
  ).getBoundingClientRect();
  let clickX = (e.clientX - containerReact.x) / scale.value;
  let clickY = (e.clientY - containerReact.y) / scale.value;
  endX.value = clickX;
  endY.value = clickY;

  return false;
};

// 判断哪些组件被框选
const judgeMaskMove = () => {
  let maskLeft = minX.value;
  let maskTop = minY.value;
  let maskRight = configsJson.value.width - maxX.value;
  let maskBottom = configsJson.value.height - maxY.value;

  layout.value.forEach((item) => {
    let left = item.x;
    let top = item.y;
    let right = configsJson.value.width - (item.x + item.width);
    let bottom = configsJson.value.height - (item.y + item.height);
    if (
      maskLeft <= left &&
      maskRight <= right &&
      maskTop <= top &&
      maskBottom <= bottom
    ) {
      let id = item.id;
      let index = layout.value.findIndex((it) => it.id == id);
      // layout.value[index].active = true;
      combineArr.value.push(layout.value[index]);
    }
  });
};
//鼠标移动
const dragMousemove = (e) => {
  //拖拽画布
  if (dragSlide.value) {
    let x = e.clientX - (window as any).stardragEvent.clientX;
    let y = e.clientY - (window as any).stardragEvent.clientY;
    $screenRef.value.scrollLeft = (window as any).startSlideX - x;
    $screenRef.value.scrollTop = (window as any).startSlideY - y;
  }
};

//鼠标抬起
const dragMouseup = (e) => {
  dragSlide.value = false;
};

const copyFunction = () => {
  if (!currentItem.value) return;
  copyedItem.value = null;
  let newItem = JSON.parse(JSON.stringify(currentItem.value));
  newItem.id = GenNonDuplicateID(6);
  newItem.x = currentItem.value.x + 100;
  newItem.y = currentItem.value.y + 100;
  copyedItem.value = newItem;
};
const cutFunction = () => {
  if (!currentItem.value) return;
  copyedItem.value = null;
  let newItem = JSON.parse(JSON.stringify(currentItem.value));
  newItem.id = GenNonDuplicateID(6);
  newItem.x = currentItem.value.x + 100;
  newItem.y = currentItem.value.y + 100;
  copyedItem.value = newItem;

  layout.value.splice(currentIndex.value, 1);
  currentIndex.value = null;
  currentId.value = "";
  showRight.value = false;
  activeName.value = "config";
  combineArr.value = [];
};

const pasteFunction = () => {
  const containerReact = (
    containercanvas.value || document.querySelector("#containercanvas")
  ).getBoundingClientRect();
  let x_value = (x.value - containerReact.left) / scale.value;
  let y_value = (y.value - containerReact.top) / scale.value;
  if (!copyedItem.value) return;
  let item = JSON.parse(JSON.stringify(copyedItem.value));
  item.id = GenNonDuplicateID(6);
  if (!isOutside.value) {
    item.x = x_value;
    item.y = y_value;
  }
  layout.value.push(item);
  combineArr.value = [];
  onActivated(item);
};

const contextMenuClick = ({ id, type }) => {
  // let index = layout.value.findIndex((it) => it.id == id);
  // console.log(index);
  if (type == "copy") {
    copyFunction();
  } else if (type == "paste") {
    pasteFunction();
  } else if (type == "cut") {
    cutFunction();
  } else if (type == "delete") {
    layout.value.splice(currentIndex.value, 1);
    currentId.value = "";
    showRight.value = false;
    activeName.value = "config";
    combineArr.value = [];
  } else if (type == "clear") {
    layout.value = [];
    currentId.value = "";
    showRight.value = false;
    activeName.value = "config";
    combineArr.value = [];
  } else if (type == "combine") {
    combindMethod();
  } else if (type == "cancleCombine") {
    cancleCombine(id);
  } else if (type == "top") {
    setZIndex(id, "top");
  } else if (type == "bottom") {
    setZIndex(id, "bottom");
  } else if (type == "up") {
    setZIndex(id, "up");
  } else if (type == "down") {
    setZIndex(id, "down");
  }
};

const setZIndex = (id: string, type: string) => {
  let maxZ = findMaxValue(layout.value, "z");
  let minZ = findMinValue(layout.value, "z");

  let index = layout.value.findIndex((it) => it.id == id);
  if (type == "top") {
    layout.value[index].z = maxZ + 1;
    newMenuRef.value.canDown = true;
  } else if (type == "bottom") {
    layout.value[index].z = minZ == 1 ? minZ : minZ - 1;
    newMenuRef.value.canDown = false;
  } else if (type == "up") {
    layout.value[index].z += 1;
    newMenuRef.value.canDown = true;
  } else if (type == "down") {
    if (layout.value[index].z == 1) {
      newMenuRef.value.canDown = false;
      return;
    }
    layout.value[index].z -= 1;
  }
};

const combindMethod = () => {
  if (combineArr.value.length > 1) {
    let res = handleSize();
    combineIds.value.forEach((it) => {
      let index = layout.value.findIndex((item) => item.id == it);
      layout.value.splice(index, 1);
    });
    layout.value.push(res);
  }
};
const cancleCombine = (id?) => {
  let item = JSON.parse(JSON.stringify(layout.value[currentIndex.value]));
  if (item.componentName != "combineGroup") return;
  let props = item.props;
  cancleCombindPosition(props.children, props.x, props.y, item);
  layout.value.splice(currentIndex.value, 1);
  props.children.forEach((it) => {
    layout.value.push(it);
  });
  // console.log("layout", layout.value);
  combineArr.value = [];
};
// 重新计算 解除组合以后的组件位置
const cancleCombindPosition = (children, propsx, propsy, item) => {
  children.forEach((it) => {
    let xSp = it.x - propsx;
    let ySp = it.y - propsy;
    it.x = item.x + xSp;
    it.y = item.y + ySp;
  });
};
</script>

<style lang="scss" scoped>
.bi-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: #18181c;
  background-image: linear-gradient(#18181c 14px, transparent 0),
    linear-gradient(90deg, transparent 14px, #86909c 0);
  background-size: 15px 15px, 15px 15px;
  .screen {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 200;
    left: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-width: none;
  }
  .screen-container {
    width: 5000px;
    height: 3000px;
    position: relative;
    // background: url(/assets/images/doit.png) repeat;
  }
  .canvas {
    position: absolute;
    left: 50%;
    top: 50%;
    transform-origin: 0 0;
  }
  .containers {
    transform-origin: 0 0;
    position: relative;
    border-radius: 15px;
  }
}
:deep(.drv) {
  border: none !important;
}
.mask {
  position: absolute;
  background: var(--active-color);
  opacity: 0.4;
  z-index: 1100;
}
:deep(.h-container .lines) {
  user-select: none;
}
:deep(.line .action) {
  user-select: none;
  color: #afb6bf !important;
}
:deep(.line .del) {
  user-select: none;
  color: var(--active-color) !important;
  font-size: 22px !important;
  visibility: visible !important;
}

:deep(.vdr-handle) {
  border-radius: 5px !important;
}
:deep(.vdr-handle-tl) {
  top: -8px;
  left: -8px;
}
:deep(.vdr-handle-tr) {
  top: -8px;
  right: -8px;
}
:deep(.vdr-handle-tm) {
  top: -8px;
  width: 25px !important;
}
:deep(.vdr-handle-ml) {
  left: -8px;
  height: 25px !important;
}
:deep(.vdr-handle-mr) {
  right: -8px;
  height: 25px !important;
}

:deep(.vdr-handle-bl) {
  bottom: -8px;
  left: -8px;
}
:deep(.vdr-handle-br) {
  bottom: -8px;
  right: -8px;
}
:deep(.vdr-handle-bm) {
  bottom: -8px;
  width: 25px !important;
}
:deep(.vdr-container.active) {
  border-color: var(--active-color);
}
</style>
